package sicnu.cs.ich.token.security.util;


import io.jsonwebtoken.*;
import io.jsonwebtoken.security.SignatureException;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Component;
import sicnu.cs.ich.common.util.CollectionUtil;
import sicnu.cs.ich.token.security.config.AppProperties;
import sicnu.cs.ich.token.security.config.TokenSecurity;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author CaiKe
 */
@Component
public class JwtUtil {
    /**
     * 用于签名 Access Token
     */
    private final Key key;
    /**
     * 用于签名 Refresh Token
     */
    private final Key refreshKey;
    private final AppProperties appProperties;

    public JwtUtil(AppProperties appProperties) {
        this.appProperties = appProperties;
        key = new SecretKeySpec(Base64.getDecoder().decode(appProperties.getJwt().getKey()), "HmacSHA512");
        refreshKey = new SecretKeySpec(Base64.getDecoder().decode(appProperties.getJwt().getRefreshKey()), "HmacSHA512");
    }

    /**
     * 返回Token是否有效
     */
    public boolean validateToken(String jwtToken, Key signKey) {
        return parseClaims(jwtToken, signKey).isPresent();
    }

    /**
     * 解析验证Token
     *
     * @param jwtToken 接收的Token
     * @param signKey  签名
     * @return 保存的信息（claims）
     */
    public Optional<Claims> parseClaims(String jwtToken, Key signKey) {
        return Optional.ofNullable(Jwts.parserBuilder().setSigningKey(signKey).build().parseClaimsJws(jwtToken).getBody());
    }

    /**
     * 不检查是否过期（验证Token是否有效）
     */
    public boolean validateWithoutExpiration(String jwtToken) {
        try {
            Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jwtToken);
            return true;
        } catch (ExpiredJwtException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException e) {
            if (e instanceof ExpiredJwtException) {
                return true;
            }
        }
        return false;
    }


    public Key getKey() {
        return this.key;
    }
}
